#include "../inc/boundingbox.h"

BoundingBox::BoundingBox()
{
	bot.clear();
	top.clear();
}

BoundingBox::BoundingBox(const BoundingBox &_bb)
{
	bot = _bb.bot;
	top = _bb.top;
}

BoundingBox::~BoundingBox()
{
	bot.~Vector3D();
	top.~Vector3D();
}

BoundingBox& BoundingBox::operator = ( const BoundingBox& _bb )
{
	bot = _bb.bot;
	top = _bb.top;
	
	return *this;
}

Vector3D BoundingBox::getBot()
{
	return bot;
}

Vector3D BoundingBox::getTop()
{
	return top;
}

double* BoundingBox::getBotArray()
{
	return bot.getArray();
}

double* BoundingBox::getTopArray()
{
	return top.getArray();
}

void BoundingBox::setBot(Vector3D _bot)
{
	bot = _bot;
}

void BoundingBox::setTop(Vector3D _top)
{
	top = _top;
}

void BoundingBox::convertsTo(BoundingBox _bbox)
{
	float ax = 100.0 / ( _bbox.getTop().getX() - _bbox.getBot().getX() );
	float ay = 100.0 / ( _bbox.getTop().getY() - _bbox.getBot().getY() );
	float az = 100.0 / ( _bbox.getTop().getZ() - _bbox.getBot().getZ() );
	float bx = - (ax * _bbox.getBot().getX());
	float by = - (ay * _bbox.getBot().getY());
	float bz = - (az * _bbox.getBot().getZ());
	
	bot.setX( ax * bot.getX() + bx );
	bot.setY( ay * bot.getY() + by );
	bot.setZ( az * bot.getZ() + bz );
	
	top.setX( ax * top.getX() + bx );
	top.setY( ay * top.getY() + by );
	top.setZ( az * top.getZ() + bz );
}

void BoundingBox::create(Mesh _mesh)
{
	bot.set( INT_MAX, INT_MAX, INT_MAX );
	top.set( INT_MIN, INT_MIN, INT_MIN );
	
	for ( int i = 0 ; i < _mesh.getNVerts() ; i++ )
	{
		if ( _mesh.getIVert(i)->getPos().getX() < bot.getX() )
			bot.setX( _mesh.getIVert(i)->getPos().getX() );
		
		if ( _mesh.getIVert(i)->getPos().getY() < bot.getY() )
			bot.setY( _mesh.getIVert(i)->getPos().getY() );
		
		if ( _mesh.getIVert(i)->getPos().getZ() < bot.getZ() )
			bot.setZ( _mesh.getIVert(i)->getPos().getZ() );
		
		if ( _mesh.getIVert(i)->getPos().getX() > top.getX() )
			top.setX( _mesh.getIVert(i)->getPos().getX() );
		
		if ( _mesh.getIVert(i)->getPos().getY() > top.getY() )
			top.setY( _mesh.getIVert(i)->getPos().getY() );
		
		if ( _mesh.getIVert(i)->getPos().getZ() > top.getZ() )
			top.setZ( _mesh.getIVert(i)->getPos().getZ() );
	}
}

void BoundingBox::create(Mesh* _mesh)
{
	bot.set( INT_MAX, INT_MAX, INT_MAX );
	top.set( INT_MIN, INT_MIN, INT_MIN );
	
	for ( int i = 0 ; i < _mesh->getNVerts() ; i++ )
	{
		if ( _mesh->getIVert(i)->getPos().getX() < bot.getX() )
			bot.setX( _mesh->getIVert(i)->getPos().getX() );
		
		if ( _mesh->getIVert(i)->getPos().getY() < bot.getY() )
			bot.setY( _mesh->getIVert(i)->getPos().getY() );
		
		if ( _mesh->getIVert(i)->getPos().getZ() < bot.getZ() )
			bot.setZ( _mesh->getIVert(i)->getPos().getZ() );
		
		if ( _mesh->getIVert(i)->getPos().getX() > top.getX() )
			top.setX( _mesh->getIVert(i)->getPos().getX() );
		
		if ( _mesh->getIVert(i)->getPos().getY() > top.getY() )
			top.setY( _mesh->getIVert(i)->getPos().getY() );
		
		if ( _mesh->getIVert(i)->getPos().getZ() > top.getZ() )
			top.setZ( _mesh->getIVert(i)->getPos().getZ() );
	}
}

void BoundingBox::create(Segment _s)
{
	bot.set( INT_MAX, INT_MAX, INT_MAX );
	top.set( INT_MIN, INT_MIN, INT_MIN );
	
	for ( list<Vertex*>::iterator it = _s.getVerts().begin() ; it != _s.getVerts().end() ; it++ )
	{
		if ( (*it)->getPos().getX() < bot.getX() )
			bot.setX( (*it)->getPos().getX() );
		
		if ( (*it)->getPos().getY() < bot.getY() )
			bot.setY( (*it)->getPos().getY() );
		
		if ( (*it)->getPos().getZ() < bot.getZ() )
			bot.setZ( (*it)->getPos().getZ() );
		
		if ( (*it)->getPos().getX() > top.getX() )
			top.setX( (*it)->getPos().getX() );
		
		if ( (*it)->getPos().getY() > bot.getY() )
			top.setY( (*it)->getPos().getY() );
		
		if ( (*it)->getPos().getZ() > bot.getZ() )
			top.setZ( (*it)->getPos().getZ() );
	}
}

void BoundingBox::create(Segment* _s)
{
	bot.set( INT_MAX, INT_MAX, INT_MAX );
	top.set( INT_MIN, INT_MIN, INT_MIN );
	
	list<Vertex*> tmp = _s->getVerts();
	for ( list<Vertex*>::iterator it = tmp.begin() ; it != tmp.end() ; it++ )
	{
		if ( (*it)->getPos().getX() < bot.getX() )
			bot.setX( (*it)->getPos().getX() );

		if ( (*it)->getPos().getY() < bot.getY() )
			bot.setY( (*it)->getPos().getY() );

		if ( (*it)->getPos().getZ() < bot.getZ() )
			bot.setZ( (*it)->getPos().getZ() );

		if ( (*it)->getPos().getX() > top.getX() )
			top.setX( (*it)->getPos().getX() );

		if ( (*it)->getPos().getY() > bot.getY() )
			top.setY( (*it)->getPos().getY() );

		if ( (*it)->getPos().getZ() > bot.getZ() )
			top.setZ( (*it)->getPos().getZ() );

	}
}

bool BoundingBox::matchBotX(BoundingBox _bbox, int _distMax)
{
	float distance = bot.getX() - _bbox.getBot().getX();
	
	if ( distance < 0 )
		distance *= -1;
	
	if ( distance <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchBotY(BoundingBox _bbox, int _distMax)
{
	float distance = bot.getY() - _bbox.getBot().getY();
	
	if ( distance < 0 )
		distance *= -1;
	
	if ( distance <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchBotZ(BoundingBox _bbox, int _distMax)
{
	float distance = bot.getZ() - _bbox.getBot().getZ();
	
	if ( distance < 0 )
		distance *= -1;
	
	if ( distance <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchTopX(BoundingBox _bbox, int _distMax)
{
	float distance = top.getX() - _bbox.getTop().getX();
	
	if ( distance < 0 )
		distance *= -1;
	
	if ( distance <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchTopY(BoundingBox _bbox, int _distMax)
{
	float distance = top.getY() - _bbox.getTop().getY();
	
	if ( distance < 0 )
		distance *= -1;
	
	if ( distance <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchTopZ(BoundingBox _bbox, int _distMax)
{
	float distance = top.getZ() - _bbox.getTop().getZ();
	
	if ( distance < 0 )
		distance *= -1;
	
	if ( distance <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchX(BoundingBox _bbox, int _distMax )
{
	float distance1 = bot.getX() - _bbox.getBot().getX();
	float distance2 = top.getX() - _bbox.getTop().getX();
	
	if ( distance1 < 0 )
		distance1 *= -1;
	
	if ( distance2 < 0 )
		distance2 *= -1;
	
	if ( distance1 <= _distMax && distance2 <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchY(BoundingBox _bbox, int _distMax )
{
	float distance1 = bot.getY() - _bbox.getBot().getY();
	float distance2 = top.getY() - _bbox.getTop().getY();
	
	if ( distance1 < 0 )
		distance1 *= -1;
	
	if ( distance2 < 0 )
		distance2 *= -1;
	
	if ( distance1 <= _distMax && distance2 <= _distMax )
		return true;
	
	else return false;
}

bool BoundingBox::matchZ(BoundingBox _bbox, int _distMax )
{
	float distance1 = bot.getZ() - _bbox.getBot().getZ();
	float distance2 = top.getZ() - _bbox.getTop().getZ();
	
	if ( distance1 < 0 )
		distance1 *= -1;
	
	if ( distance2 < 0 )
		distance2 *= -1;
	
	if ( distance1 <= _distMax && distance2 <= _distMax )
		return true;
	
	else return false;
}

void BoundingBox::print()
{
	cout<<"Bot : ( "<<bot.getX()<<" , "<<bot.getY()<<" , "<<bot.getZ()<<" )"<<endl;
	cout<<"Top : ( "<<top.getX()<<" , "<<top.getY()<<" , "<<top.getZ()<<" )"<<endl;
}

void BoundingBox::display(float _r, float _g, float _b)
{
	glDisable ( GL_LIGHTING );
	glColor3f ( _r, _g, _b );
	
	/* Bottom face. */
	glBegin( GL_LINE_LOOP );
		glVertex3dv ( bot.getArray() );
		glVertex3d ( bot.getX(), top.getY(), bot.getZ() );
		glVertex3d ( top.getX(), top.getY(), bot.getZ() );
		glVertex3d ( top.getX(), bot.getY(), bot.getZ() );
	glEnd();
	
	/* Top face. */
	glBegin( GL_LINE_LOOP );
		glVertex3dv ( top.getArray() );
		glVertex3d ( top.getX(), bot.getY(), top.getZ() );
		glVertex3d ( bot.getX(), bot.getY(), top.getZ() );
		glVertex3d ( bot.getX(), top.getY(), top.getZ() );
	glEnd();
	
	/* Front face. */
	glBegin( GL_LINE_LOOP );
		glVertex3dv ( bot.getArray() );
		glVertex3d ( bot.getX(), top.getY(), bot.getZ() );
		glVertex3d ( bot.getX(), top.getY(), top.getZ() );
		glVertex3d ( bot.getX(), bot.getY(), top.getZ() );
	glEnd();
	
	/* Back face. */
	glBegin( GL_LINE_LOOP );
		glVertex3dv ( top.getArray() );
		glVertex3d ( top.getX(), bot.getY(), top.getZ() );
		glVertex3d ( top.getX(), bot.getY(), bot.getZ() );
		glVertex3d ( top.getX(), top.getY(), bot.getZ() );
	glEnd();
	
	/* Left face. */
	glBegin( GL_LINE_LOOP );
		glVertex3dv ( bot.getArray() );
		glVertex3d ( top.getX(), bot.getY(), bot.getZ() );
		glVertex3d ( top.getX(), bot.getY(), top.getZ() );
		glVertex3d ( bot.getX(), bot.getY(), top.getZ() );
	glEnd();
	
	/* right face. */
	glBegin( GL_LINE_LOOP );
		glVertex3dv ( top.getArray() );
		glVertex3d ( bot.getX(), top.getY(), top.getZ() );
		glVertex3d ( bot.getX(), top.getY(), bot.getZ() );
		glVertex3d ( top.getX(), top.getY(), bot.getZ() );
	glEnd();
	
	glEnable( GL_LIGHTING );
}
